How to observe the moment when the view is added to the super view.
Sometimes it is useful to know when the view has added a subview to another view. For example, it is required before we can activate the autolayout constraints.
This can be achieved by observing the moment when the view is moved to the window, as in the case of the UIView
it happens at the time when is added as a subview.
To do that we can create UIView
subclass that will override method didMoveToWindow().
public final class SuperviewObserver: UIView {
private let observer: (_ this: UIView, _ superview: UIView) -> Void
public init(observer: @escaping (_ this: UIView, _ superview: UIView) -> Void) {
self.observer = observer
super.init(frame: .zero)
}
@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public override func didMoveToWindow() {
super.didMoveToWindow()
guard let superview = superview?.superview else { return }
observer(self, superview)
removeFromSuperview()
}
}
We can make this custom subclass more convenient to use, by creating an extension method:
public protocol UIViewProtocol {}
extension UIView: UIViewProtocol {}
public extension UIViewProtocol where Self: UIView {
func onDidMoveToSubview(closure: @escaping (_ view: Self, _ superview: UIView) -> Void) {
addSubview(
SuperviewObserver { [unowned self] this, superview in
closure(self, superview)
}
)
}
}
UIViewProtocol
protocol is added, to be able to get the exact type of the UIView
.
let superview = UIView()
let view = CustomSubclass()
view.onDidMoveToSubview { this, superview in
NSLayoutConstraint.activate([
this.leadingAnchor.constraint(equalTo: superview.leadingAnchor) // this is type of CustomSubclass
...
])
}
superview.addSubview(view)